package com.enation.app.javashop.core.trade.order.model.vo;

import com.enation.app.javashop.core.aftersale.model.enums.RefundStatusEnum;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.enums.*;
import com.enation.app.javashop.core.trade.order.support.OrderOperateChecker;
import com.enation.app.javashop.core.trade.order.support.OrderOperateFlow;
import com.enation.app.javashop.core.trade.order.support.OrderStep;
import com.enation.app.javashop.framework.util.StringUtil;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Map;

/**
 * 订单可进行的操作
 *
 * @author Snow create in 2018/5/15
 * @version v2.0
 * @since v7.0.0
 */
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
@Data
public class OrderOperateAllowable implements Serializable {

    @ApiModelProperty(value = "是否允许被取消")
    private Boolean allowCancel;

    @ApiModelProperty(value = "是否允许被确认")
    private Boolean allowConfirm;

    @ApiModelProperty(value = "是否允许被支付")
    private Boolean allowPay;

    @ApiModelProperty(value = "是否允许被发货")
    private Boolean allowShip;

    @ApiModelProperty(value = "是否允许被收货")
    private Boolean allowRog;

    @ApiModelProperty(value = "是否允许被评论")
    private Boolean allowComment;

    @ApiModelProperty(value = "是否允许被完成")
    private Boolean allowComplete;

    @ApiModelProperty(value = "是否允许申请售后")
    private Boolean allowApplyService;

    @ApiModelProperty(value = "是否允许取消(售后)")
    private Boolean allowServiceCancel;

    @ApiModelProperty(value = "是否允许查看物流信息")
    private Boolean allowCheckExpress;

    @ApiModelProperty(value = "是否允许更改收货人信息")
    private Boolean allowEditConsignee;

    @ApiModelProperty(value = "是否允许更改价格")
    private Boolean allowEditPrice;

    @ApiModelProperty(value = "是否允许处理售后")
    private Boolean allowAuditAfterSell;

    @ApiModelProperty(value = "是否允许删除订单")
    private Boolean allowDelete;

    @ApiModelProperty(value = "是否允许邀请拼团")
    private Boolean allowInvitePintuan;


    /**
     * 空构造器
     */
    public OrderOperateAllowable() {

    }


    /**
     * 根据各种状态构建对象
     * 状态--->>> 按钮映射
     * @param order
     */
    public OrderOperateAllowable(OrderDO order) {

        String paymentType = order.getPaymentType();

        //定位到相应的订单流程，并构建checker  FLOW --->>>> 在线支付订单 、货到付款订单、拼团订单（每种类型订单需要单独控制每个订单状态对应的可操作按钮）
        Map<OrderStatusEnum, OrderStep> flow = OrderOperateFlow.getFlow(PaymentTypeEnum.valueOf(paymentType), OrderTypeEnum.valueOf(order.getOrderType()));

//如需调试时可打开面注释
//        if (logger.isDebugEnabled()) {
//
//            logger.debug("为订单获取flow:");
//            logger.debug(order.toString());
//            logger.debug("获取到的flow为：");
//            logger.debug(flow.toString());
//
//        }

        // 构建订单可操作选择器（根据订单类型FLOW）  FLOW--->>>>orderStatus---->>>order_oeperate
        OrderOperateChecker orderOperateChecker = new OrderOperateChecker(flow);

        //订单状态
        OrderStatusEnum orderStatus = OrderStatusEnum.valueOf(order.getOrderStatus());

        String serviceStatus = order.getServiceStatus();

        //是否允许被取消
        this.allowCancel = orderOperateChecker.checkAllowable(orderStatus, OrderOperateEnum.CANCEL);

        //是否允许被确认
        this.allowConfirm = orderOperateChecker.checkAllowable(orderStatus, OrderOperateEnum.CONFIRM);

        //是否允许被支付
        this.allowPay = orderOperateChecker.checkAllowable(orderStatus, OrderOperateEnum.PAY);


        //是否允许被发货： 要有特殊的要求：申请了售后，或售后已经被通过了
        this.allowShip = orderOperateChecker.checkAllowable(orderStatus, OrderOperateEnum.SHIP)
                && !ServiceStatusEnum.APPLY.name().equals(serviceStatus)
                && !ServiceStatusEnum.PASS.name().equals(serviceStatus);

        //是否允许被收货
        this.allowRog = orderOperateChecker.checkAllowable(orderStatus, OrderOperateEnum.ROG);

        //发货状态
        String shipStatus = order.getShipStatus();

        //评论状态
        String commentStatus = order.getCommentStatus();

        //付款状态
        String payStatus = order.getPayStatus();

        //是否允许被评论: 收货后可以评论，且评论未完成（评论完成后就不可以再评论了）
        this.allowComment = CommentStatusEnum.UNFINISHED.value().equals(commentStatus) && ShipStatusEnum.SHIP_ROG.value().equals(shipStatus);

        //是否允许被完成
        this.allowComplete = orderOperateChecker.checkAllowable(orderStatus, OrderOperateEnum.COMPLETE);

        //是否允许被申请售后 = 已收货 && 未申请过售后 && 订单是已收货状态
        this.allowApplyService = ShipStatusEnum.SHIP_ROG.value().equals(shipStatus) && ServiceStatusEnum.NOT_APPLY.name().equals(serviceStatus);

        //订单是否允许取消(售后) = 支付状态已付款  &&  订单已付款 && (未申请过售后||售后过期)
        this.allowServiceCancel = (OrderStatusEnum.PAID_OFF.value().equals(orderStatus.value()) || OrderStatusEnum.FORMED.value().equals(orderStatus.value()))
                && (ServiceStatusEnum.NOT_APPLY.name().equals(serviceStatus) || ServiceStatusEnum.EXPIRED.name().equals(serviceStatus));

        //是否允许查看物流信息 = 当物流单号不为空并且物流公司不为空
        this.allowCheckExpress = order.getLogiId()!=null && ( order.getShippingType()!=null && order.getShippingType().equals(ShipTypeEnum.GLOBAL.getText()));

        //是否允许更改收货人信息 = 发货状态未发货,待发货才能修改地址
        this.allowEditConsignee = ShipStatusEnum.SHIP_NO.value().equals(order.getShipStatus()) && orderStatus.equals(OrderStatusEnum.PAID_OFF);

        //是否允许更改价格 = （在线支付 && 未付款）||（货到付款 && 未发货）
        this.allowEditPrice = (PaymentTypeEnum.ONLINE.value().equals(order.getPaymentType()) && PayStatusEnum.PAY_NO.value().equals(order.getPayStatus()))
                && orderStatus.equals(OrderStatusEnum.CONFIRM);

        //是否允许商家删除
        this.allowDelete = order.getOrderStatus().equals(OrderStatusEnum.CANCELLED.value());

        //是否允许邀请好友来拼团
        this.allowInvitePintuan = OrderStatusEnum.PAID_OFF.value().equals(orderStatus.value()) && OrderTypeEnum.pintuan.name().equals(order.getOrderType())
                && ServiceStatusEnum.NOT_APPLY.name().equals(serviceStatus);
    }


}
